package ytcp

import (
	"bytes"
	"errors"
	"fmt"

	"gitee.com/johng/gf/g/encoding/gjson"

	"gitee.com/johng/gf/g/encoding/gparser"
	"gitee.com/johng/gf/g/net/gtcp"
	"gitee.com/johng/gf/g/util/gconv"
)

//数据包header结构
type Header struct {
	ContentLength string      `json:"contentlength"`  //数据包内容大小,动态获取,无需设置
	Padding       string      `json:"padding"`        //自动补全header到数据包header规定长度，默认1024字节即1KB
	Checksum      string      `json:"checksum"`       //数据包内容校验和
	HData         interface{} `json:"data,omitempty"` //header额外参数设置,可忽略
}

//数据包结构
type PKG struct {
	Header
	Body []byte
}

const (
	HEADER_LENGTH = 1024
)

func Sendpkg(content []byte, conn interface{}, headata ...interface{}) error {
	if len(content) == 0 {
		return errors.New("发送数据包不能为空")
	}
	pkg := new(PKG)
	pkg.Body = content
	if len(headata) > 0 {
		pkg.HData = headata[0]
	}
	pkgheadbyte, err := pkg.EncodeHeader()
	if err != nil {
		return err
	}
	data := BytesCombine(pkgheadbyte, pkg.Body)
	switch connt := conn.(type) {
	case *gtcp.Conn:
		return connt.Send(data)
	case *gtcp.PoolConn:
		return connt.Send(data)
	default:
		return errors.New("未匹配到正确的链接类型")
	}
}

func Recvpkg(conn *gtcp.Conn) (hdata []byte, content []byte, err error) {
	head := new(Header)
	datahead, err := conn.Recv(HEADER_LENGTH) //定长取header,解析并获取body长度
	if err != nil {

		return hdata, content, err
	}
	if len(datahead) > 0 { //解析header

		if err := gjson.DecodeTo(datahead, head); err != nil {

			return hdata, content, err
		}
		if len(head.ContentLength) == 0 || head.ContentLength == "" {
			fmt.Println("未获取到content-length")
			return hdata, content, errors.New("未获取到content-length")
		}

		content, err := conn.Recv(gconv.Int(head.ContentLength))
		if err != nil {

			return hdata, content, err
		}
		if len(content) > 0 {

			if gtcp.Checksum(content) != gconv.Uint32(head.Checksum) {
				fmt.Println("获取数据不完整")
				return hdata, content, err
			}

			if head.HData != nil {
				hdata, err = gjson.Encode(head.HData)
			}

			return hdata, content, nil
		}
	}
	return hdata, content, errors.New("未获取到header头信息")
}

func (pkg *PKG) EncodeHeader() ([]byte, error) {
	var headbyte []byte
	var err error
	pkg.Header.ContentLength = gconv.String(len(pkg.Body))
	pkg.CheckSum()
	headbyte, err = gparser.VarToJson(pkg.Header)

	if err != nil {
		return nil, err
	}

	if len(headbyte) > HEADER_LENGTH {
		return nil, errors.New("header长度不能超过" + gconv.String(HEADER_LENGTH))
	} else {
		paddingstr := ""
		for i := len(headbyte); i < HEADER_LENGTH; i++ {
			paddingstr += "0"
		}
		pkg.Header.Padding = paddingstr
		headbyte, err = gparser.VarToJson(pkg.Header)
		if err != nil {
			return nil, err
		}
	}
	return headbyte, nil

}
func (pkg *PKG) CheckSum() {
	if len(pkg.Body) == 0 {
		pkg.Header.Checksum = gconv.String("0")
	}
	pkg.Header.Checksum = gconv.String(int(gtcp.Checksum(pkg.Body)))

}

func BytesCombine(pBytes ...[]byte) []byte {
	return bytes.Join(pBytes, []byte(""))
}
